#include <iostream>
#include <string>
#include <memory>

// 抽象基类
class Car
{
public:
    virtual void intro() = 0;
    virtual ~Car() {}
};
class Bmw : public Car
{
public:
    void intro()
    {
        std::cout << "宝马-德国品牌-始于1916" << std::endl;
    }
};
class Toyota : public Car
{
public:
    void intro()
    {
        std::cout << "丰田-日本品牌-始于1937" << std::endl;
    }
};
class Ford : public Car
{
public:
    void intro()
    {
        std::cout << "福特-美国品牌-始于1903" << std::endl;
    }
};

// 简单工厂
// class CarFactory
// {
// public:
//     static std::shared_ptr<Car> create(const std::string &brand)
//     {
//         if (brand == "宝马")
//             // return std::make_shared<BMW>();
//             // return new BMW; // err
//             return std::shared_ptr<BMW>(new BMW);
//         else if (brand == "丰田")
//             return std::make_shared<TOYOTA>();
//         else
//         {
//             //...
//         }
//     }
// };

// 工厂方法
// 每一个具体类都有一个工厂

// 工厂基类
class CarFactory
{
public:
    virtual std::shared_ptr<Car> Create() = 0;
    virtual ~CarFactory(){};
};

class BmwFactory : public CarFactory
{
public:
    std::shared_ptr<Car> Create()
    {
        return std::make_shared<Bmw>();
    }
};
class ToyotaFactory : public CarFactory
{
public:
    std::shared_ptr<Car> Create()
    {
        return std::make_shared<Toyota>();
    }
};
class FordFactory : public CarFactory
{
public:
    std::shared_ptr<Car> Create()
    {
        return std::make_shared<Ford>();
    }
};

// 缺点：Create的参数都是一样的

void ProduceCar(std::shared_ptr<CarFactory> factory)
{
    // 创建car对象时，等号两边，都不依赖具体类，而是依赖抽象
    // 将依赖具体类的动作，“驱赶”到当前局部域之外
    std::shared_ptr<Car> car = factory->Create();
    car->intro();
}

int main()
{
    ProduceCar(std::make_shared<ToyotaFactory>());
    ProduceCar(std::make_shared<FordFactory>());
    ProduceCar(std::make_shared<BmwFactory>());

    return 0;
}

// int main()
// {
//     std::shared_ptr<Car> car1 = CarFactory::create("宝马");
//     car1->intro();

//     std::shared_ptr<Car> car2 = CarFactory::create("丰田");
//     car2->intro();

//     // std::shared_ptr<BMW> sp(new BMW);
//     // sp->intro();
//     // std::shared_ptr<Car> sp2;
//     // sp2 = sp;

//     // 智能指针：
//     // 构造：父类智能指针，可以用子类原生指针构造
//     // 赋值operator==：父类智能指针，可以用子类智能指针赋值，但不可以用子类原生指针赋值
//     // U* shall be implicitly convertible to T* (where T is shared_ptr's template parameter).

//     return 0;
// }